#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>

#define NUM 1024

struct MyFILE
{
    int fd;
    char buffer[1024];
    int end;//当前缓冲区的结尾
};

typedef struct MyFILE MyFILE;

MyFILE* fopen_(const char* path,const char* mode)
{
    assert(path);
    assert(mode);

    MyFILE* fp = NULL;

    if(strcmp(mode,"r") == 0)
    {     

    }else if(strcmp(mode,"r+") == 0)
    {

    }else if(strcmp(mode,"w") == 0)
    {
        int fd = open(path,O_WRONLY | O_TRUNC | O_CREAT,0666);
        if(fd < 0)
        {
            //打开失败,这里可以直接省略fd<0的判断，因为返回一开始的fd就是NULL
            return NULL;
        }else
        {
            fp = (MyFILE*)malloc(sizeof(MyFILE));
            memset(fp,0,sizeof(MyFILE));
            fp->fd = fd;
        }

    }else if(strcmp(mode,"w+") == 0)
    {

    }else if(strcmp(mode,"a") == 0)
    {

    }else if(strcmp(mode,"a+") == 0)
    {

    }

    return fp;
}

void fputs_(const char* s,MyFILE* fp)
{
    assert(s);
    assert(fp);

    strcpy(fp->buffer + fp->end,s);//abcd\0
    fp->end += strlen(s);//这里将end指向buff的最后

    printf("%s\n",fp->buffer);

    if(fp->fd == 0)
    {
        //标准输入
    }else if(fp->fd == 1)
    {
        //标准输出
        if(fp->buffer[fp->end-1] == '\n')
        {
            //这里有个疑问，为什么是stderr呢？？ stdout为什么不行
            fprintf(stderr,"fflush: %s",fp->buffer);//2
            write(fp->fd,fp->buffer,fp->end);
            fp->end = 0;
        }

    }else if(fp->fd == 2)
    {
        //标准错误

    }else
    {
        //其他文件
    }
    
}

void fflush_(MyFILE* fp)
{
    assert(fp);

    //说明有数据，开始刷新
    if(fp->end != 0)
    {
        //将数据写到了内核
        write(fp->fd,fp->buffer,fp->end);
        syncfs(fp->fd);//将数据刷新到外设，这里刷新到了磁盘上
        fp->end = 0;
    }
}

void fclose_(MyFILE* fp)
{
    assert(fp);
    fflush_(fp);

    close(fp->fd);
    free(fp);    
}

int main()
{
    close(1);
    MyFILE* fp = fopen_("./log.txt","w");
    if(fp == NULL)
    {
        printf("open file error\n");
    }

    fputs_("one: hello world\n",fp);
    sleep(1);
    fputs_(" two: hello world\n",fp);
    sleep(1);
    fputs_(" three: hello world\n",fp);
    sleep(1);
    fputs_(" four: hello world\n",fp);
    sleep(1);

    fclose_(fp);

    return 0;
}

// int main()
// {

//     //C语言提供的
//     printf("hello printf\n");
//     fprintf(stdout,"hello fprintf\n");
//     const char* s = "hello fputs\n";
//     fputs(s,stdout);

//     //OS提供的
//     const char* ss = "hello write\n";
//     write(1,ss,strlen(ss));

//     //在调用fork的时候，上面的程序已经被执行完了,但并不代表进数据已经刷新了 
//     fork();//创建子进程

//     return 0;
// }